package com.xnyzc.lhy.resource.controller.oss;


import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.xnyzc.lhy.common.entity.Qd;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.OSSException;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.oss.OSSFileType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.order.entity.mq.OaCOrderPersonal;
import com.xnyzc.lhy.resource.entity.oss.OaOssFile;
import com.xnyzc.lhy.resource.service.oss.IOaOssFileService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 阿里云oss上传文件对照表 前端控制器
 * </p>
 *
 * @author liuju
 * @since 2019-08-05
 */
@Slf4j
@RestController
@RequestMapping("/oa/oss")
public class OaOssFileController {

    @Value("${global.ali.oss.endpoint}")
    private String endpoint;
    @Value("${global.ali.oss.accessKeyId}")
    private String accessKeyId;
    @Value("${global.ali.oss.accessKeySecret}")
    private String accessKeySecret;
    @Value("${global.ali.oss.bucketName}")
    private String bucketName;
    @Value("${global.ali.oss.validityTime}")
    private Integer validityTime;

    @Autowired
    IOaOssFileService iOaOssFileService;

    /**
     * 单文件上传
     *
     * @return
     */
    @ApiOperation(value = "单文件上传", notes = "单文件上传")
    @PostMapping(value = "uploadFile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Rv uploadFile(@ApiParam(name = "file", value = "文件") @RequestParam("file") MultipartFile file,
                         @ApiParam(name = "fileType", value = "文件类型") @RequestParam("fileType") String fileType) throws IOException {
        if (CheckUtil.objIsEmpty(file) || CheckUtil.strIsEmpty(fileType)) {
            throw PangException.create(EErrorCode.missingArg);
        }
        System.out.println("fileType---->" + fileType);
        // 上传文件流
        byte[] content;
        try {
            content = file.getBytes();
        } catch (IOException e) {
            log.info("文件内容为空，不可上传");
            throw PangException.create(EErrorCode.dataParseError);
        }
        //获取文件名
        String fileName = file.getOriginalFilename();
        String extendName = "";
        if (!CheckUtil.strIsEmpty(fileName)) {
            // 获取文件后缀
            extendName = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();
        }
        fileName = String.valueOf(IDUtil.nextId());
        // oss服务存储路径
        String saveFilePath = OSSFileType.findByPath(fileType).getValue();
        // 保存文件相关信息
        Long fileId = iOaOssFileService.getFileId(fileName, extendName, saveFilePath);
        //上传到阿里云时候的名称及存储路径
        String aliFileName = fileId + extendName;
        //获得头像在阿里云图片存储路径
        String aliUrl = saveFilePath + aliFileName;
        URL url = null;
        if(Integer.parseInt(fileType) != 6){//不是apk文件
            log.info("============ 开始单上传文件 =============");
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.putObject(bucketName, aliUrl, new ByteArrayInputStream(content));
            // 设置URL过期时间时间（单位分钟）。
            Date expiration = DateUtil.dateAddMinutes(new Date(), validityTime);
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            url = ossClient.generatePresignedUrl(bucketName, aliUrl, expiration);
            // 关闭OSSClient。
            ossClient.shutdown();
            log.info("============ 单文件上传结束 =============");
        }else if(Integer.parseInt(fileType) == 6){//apk文件上传
            final File tempFile = File.createTempFile(fileName, extendName);
            //MultipartFile  转换为 File
            file.transferTo(tempFile);
            // 创建OSSClient实例。
            OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            try {
                //容器不存在，就创建
                if(! ossClient.doesBucketExist(bucketName)){
                    ossClient.createBucket(bucketName);
                    CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                    createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                    ossClient.createBucket(createBucketRequest);
                }
                PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, aliUrl, tempFile));
                //设置权限 这里是公开读
                ossClient.setBucketAcl(bucketName,CannedAccessControlList.PublicRead);
                if(null != result){
                    log.info("==========>OSS文件上传成功,OSS地址："+aliUrl);
                }
            }catch (OSSException oe){
                log.error(oe.getMessage());
            }catch (ClientException ce){
                log.error(ce.getMessage());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭
                ossClient.shutdown();
            }
            //删除临时生成的文件
            deleteFile(tempFile);
            // 设置URL过期时间时间（单位分钟）。
            Date expiration = DateUtil.dateAddMinutes(new Date(), validityTime);
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            url = ossClient.generatePresignedUrl(bucketName, aliUrl, expiration);
        }

        // 返回数据
        Qd qd = Qd.create().add("fileId", fileId).add("fileUrl", url);
        return Rv.wrap(qd);
    }

    /**
     * 删除临时文件
     *
     * @param files
     */
    private void deleteFile(File... files) {
        for (File file : files) {
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     * 录音文件上传
     *
     * @return
     */
    @ApiOperation(value = "录音文件上传", notes = "录音文件上传")
    @PostMapping(value = "uploadMp3File",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Rv uploadMp3File(@ApiParam(name = "file", value = "文件") @RequestParam("file") MultipartFile file) {
        if (CheckUtil.objIsEmpty(file)) {
            throw PangException.create(EErrorCode.missingArg);
        }
       String fileType = "8";
        // 上传文件流
        byte[] content;
        try {
            content = file.getBytes();
        } catch (IOException e) {
            log.info("文件内容为空，不可上传");
            throw PangException.create(EErrorCode.dataParseError);
        }
        //获取文件名
        String fileName = file.getOriginalFilename();
        String extendName = "";
        if (!CheckUtil.strIsEmpty(fileName)) {
            // 获取文件后缀
            extendName = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();
        }
        fileName = String.valueOf(IDUtil.nextId());
        // oss服务存储路径
        String saveFilePath = OSSFileType.findByPath(fileType).getValue();
        // 保存文件相关信息
        Long fileId = iOaOssFileService.getFileId(fileName, extendName, saveFilePath);
        //上传到阿里云时候的名称及存储路径
        String aliFileName = fileId + extendName;
        //获得头像在阿里云图片存储路径
        String aliUrl = saveFilePath + aliFileName;
        log.info("============ 开始单上传文件 =============");
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, aliUrl, new ByteArrayInputStream(content));
        // 设置URL过期时间时间（单位分钟）。
        Date expiration = DateUtil.dateAddMinutes(new Date(), validityTime);
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(bucketName, aliUrl, expiration);
        // 关闭OSSClient。
        ossClient.shutdown();
        log.info("============ 单文件上传结束 =============");
        // 返回数据
        Qd qd = Qd.create().add("fileId", fileId).add("fileUrl", url);
        return Rv.wrap(qd);
    }

    @ApiOperation(value = "更新乘客订单中上传录音文件id", notes = "更新乘客订单中上传录音文件id")
    @GetMapping(value = "upOaCOrderPersonal")
    public Rv upOaCOrderPersonal(@ApiParam(name = "fileId", value = "文件ID") @RequestParam("fileId") String fileId,
                                 @ApiParam(name = "orderNo", value = "订单ID") @RequestParam("orderNo") String orderNo) {
        if(CheckUtil.objIsEmpty(fileId) || CheckUtil.objIsEmpty(orderNo)){
            throw PangException.create(EErrorCode.missingArg);
        }
        //绑定录音id到乘客订单中
        Integer sum = iOaOssFileService.saveOaCOrderPersonal(orderNo,fileId);
        if(sum < 1 || CheckUtil.objIsEmpty(sum)){
            throw PangException.create(EErrorCode.orderFailure);
        }
        return Rv.wrap();
    }

    @ApiOperation(value = "更新乘客订单中上传录音文件id2", notes = "更新乘客订单中上传录音文件id2")
    @GetMapping(value = "NewUpOaCOrderPersonal")
    public Rv NewUpOaCOrderPersonal(@ApiParam(name = "fileId", value = "文件ID") @RequestParam("fileId") String fileId,
                                    @ApiParam(name = "orderNo", value = "订单ID") @RequestParam("orderNo") String orderNo,
                                    @ApiParam(name = "fileName", value = "文件名字") @RequestParam("fileName") String fileName,
                                    @ApiParam(name = "extendName", value = "文件后缀") @RequestParam("extendName") String extendName,
                                    @ApiParam(name = "saveFilePath", value = "文件保存路径") @RequestParam("saveFilePath") String saveFilePath) {
        if(CheckUtil.objIsEmpty(fileId) || CheckUtil.objIsEmpty(orderNo)
                || CheckUtil.objIsEmpty(fileName) || CheckUtil.objIsEmpty(extendName) || CheckUtil.objIsEmpty(saveFilePath)){
            throw PangException.create(EErrorCode.missingArg);
        }
        //绑定录音id到乘客订单中
        Integer sum = iOaOssFileService.saveOaCOrderPersonal(orderNo,fileId);
        if (sum == -1) {
            return Rv.wrap("录音文件已保存!");
        }
        if(sum < 1 || CheckUtil.objIsEmpty(sum)){
            throw PangException.create(EErrorCode.orderFailure);
        }
        //创建与保存OOS信息
        OaOssFile oaOssFile = new OaOssFile();
        Date date = new Date();
        //Long newFileId = Long.parseLong(fileId);

        oaOssFile.setOssFileId(fileId);
        oaOssFile.setFileName(fileName);
        oaOssFile.setExtendName(extendName);
        oaOssFile.setFilePath(saveFilePath);
        oaOssFile.setCreateTime(date);
        oaOssFile.setCreateUser(TokenUtil.getTokenUserId());
        oaOssFile.setUpdateTime(date);
        oaOssFile.setUpdateUser(TokenUtil.getTokenUserId());

        iOaOssFileService.saveOaOssFile(oaOssFile);

        return Rv.wrap();
    }
    /**
     * 获取录音文件访问路径(单文件)
     *
     * @return
     */
    @ApiOperation(value = "获取录音文件访问路径", notes = "获取录音文件访问路径")
    @GetMapping(value = "getMp3FileUrl")
    public Rv getMp3FileUrl(@ApiParam(name = "orderNo", value = "录音文件对应订单号") @RequestParam("orderNo") String orderNo) {
        //这里是针对录音文件 ---做的特殊处理
        String endpoint2 = "https://oss-cn-hangzhou.aliyuncs.com";
        String accessKeyId2 = "LTAICT3skBs9BUDT";
        String accessKeySecret2 = "SxDE4xCRB4SroN1Ylucmarwo7cHGWq";
        String bucketName2 = "qlycoss002";
        Integer validityTime2 = 60;
        if (CheckUtil.objIsEmpty(orderNo)) {
            throw PangException.create(EErrorCode.missingArg);
        }
        //获取订单号对应的乘客订单所有信息
        OaCOrderPersonal oaCOrderPersonal =iOaOssFileService.selectOaCOrderPersonalByOrderNo(orderNo);
        if(CheckUtil.objIsEmpty(oaCOrderPersonal)){
            throw PangException.create(EErrorCode.infoIsNull);
        }
        if(oaCOrderPersonal.getUploadId() == null){//确保获取不到空的上传录音文件id
            throw PangException.create(EErrorCode.infoIsNull);
        }
        Long fileId = Long.parseLong(oaCOrderPersonal.getUploadId());
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint2, accessKeyId2, accessKeySecret2);
        // 设置URL过期时间时间（单位分钟）。
        Date expiration = DateUtil.dateAddMinutes(new Date(), validityTime2);

        OaOssFile oaOssFile = iOaOssFileService.getById(fileId);
        if (CheckUtil.objIsEmpty(oaOssFile)) {
            throw PangException.create(EErrorCode.unData);
        }
        StringBuilder fileUrl = new StringBuilder();
        fileUrl.append(oaOssFile.getFilePath()).append(oaOssFile.getOssFileId()).append(oaOssFile.getExtendName());
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(bucketName2, String.valueOf(fileUrl), expiration);

        // 返回数据
        Qd qd = Qd.create().add("fileUrl", url);

        return Rv.wrap(qd);
    }
    /**
     * 获取文件访问路径(单文件)
     *
     * @return
     */
    @ApiOperation(value = "获取文件访问路径", notes = "获取文件访问路径")
    @GetMapping(value = "getFileUrl")
    public Rv getFileUrl(@ApiParam(name = "fileId", value = "文件ID") @RequestParam("fileId") Long fileId) {

        if (CheckUtil.objIsEmpty(fileId)) {
            throw PangException.create(EErrorCode.missingArg);
        }

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 设置URL过期时间时间（单位分钟）。
        Date expiration = DateUtil.dateAddMinutes(new Date(), validityTime);

        OaOssFile oaOssFile = iOaOssFileService.getById(fileId);
        if (CheckUtil.objIsEmpty(oaOssFile)) {
            throw PangException.create(EErrorCode.unData);
        }
        StringBuilder fileUrl = new StringBuilder();
        fileUrl.append(oaOssFile.getFilePath()).append(oaOssFile.getOssFileId()).append(oaOssFile.getExtendName());
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(bucketName, String.valueOf(fileUrl), expiration);

        // 返回数据
        Qd qd = Qd.create().add("fileUrl", url);

        return Rv.wrap(qd);
    }
    /**
     * 多文件上传
     *
     * @return
     */
    @ApiOperation(value = "多文件上传", notes = "多文件上传")
    @PostMapping(value = "uploadFiles")
    public Rv uploadFiles(@ApiParam(name = "files", value = "文件") @RequestParam("files") MultipartFile[] files,
                          @ApiParam(name = "fileType", value = "文件类型") @RequestParam("fileType") String fileType) {
        if (CheckUtil.objIsEmpty(files) || CheckUtil.strIsEmpty(fileType)) {
            throw PangException.create(EErrorCode.missingArg);
        }
        // 文件数统计
        Integer count = 0;
        List<Qd> qdList = new ArrayList<>();
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        for (int i = 0; i < files.length; i++) {
            if (!files[i].isEmpty()) {
                // 上传文件流
                byte[] content;
                try {
                    content = files[i].getBytes();
                } catch (IOException e) {
                    log.info("文件内容为空，不可上传");
                    throw PangException.create(EErrorCode.dataParseError);
                }
                // 获取文件名称
                String fileName = files[i].getOriginalFilename();
                String extendName = "";
                if (!CheckUtil.strIsEmpty(fileName)) {
                    // 获取文件后缀
                    extendName = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();
                }

                // 源文件名加随机数
                fileName = String.valueOf(IDUtil.nextId());

                // oss服务存储路径
                String saveFilePath = OSSFileType.findByPath(fileType).getValue();
                // 保存文件相关信息
                Long fileId = iOaOssFileService.getFileId(fileName, extendName, saveFilePath);
                //上传到阿里云时候的图片名称及图片存储路径
                String aliFileName = fileId + extendName;
                //获得头像在阿里云图片存储路径
                String aliUrl = saveFilePath + aliFileName;

                log.info("===========第{}个文件开始上传=========", i + 1);

                ossClient.putObject(bucketName, aliUrl, new ByteArrayInputStream(content));
                // 设置URL过期时间时间（单位分钟）。
                Date expiration = DateUtil.dateAddMinutes(new Date(), validityTime);
                // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
                URL url = ossClient.generatePresignedUrl(bucketName, aliUrl, expiration);
                count++;
                log.info("===========第{}个文件上传结束=========", i + 1);
                // 返回数据
                qdList.add(Qd.create().add("fileId", fileId).add("fileUrl", url));
            }
        }
        // 关闭OSSClient。
        ossClient.shutdown();

        return Rv.wrap(qdList);
    }

    /**
     * 获取文件访问路径(多文件)
     *
     * @return
     */
    @ApiOperation(value = "获取多文件访问路径", notes = "获取多文件访问路径")
    @GetMapping(value = "getFileUrls")
    public Rv getFileUrls(@ApiParam(name = "fileIds", value = "多文件ID") String fileIds) {

        if (CheckUtil.objIsEmpty(fileIds)) {
            throw PangException.create(EErrorCode.missingArg);
        }
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 设置URL过期时间时间（单位分钟）。
        Date expiration = DateUtil.dateAddMinutes(new Date(), validityTime);

        List<OaOssFile> oaOssFileList = iOaOssFileService.getFileUrl(fileIds);
        List<Qd> qdList = new ArrayList<>();
        for (OaOssFile oss : oaOssFileList) {
            StringBuilder fileUrl = new StringBuilder();
            fileUrl.append(oss.getFilePath()).append(oss.getOssFileId()).append(oss.getExtendName());
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            URL url = ossClient.generatePresignedUrl(bucketName, String.valueOf(fileUrl), expiration);
            // 返回数据
            qdList.add(Qd.create().add("fileUrl", url));
        }
        return Rv.wrap(qdList);
    }
}
